home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-10 | 15.4 KB | 603 lines | [TEXT/MMCC] |
- //View3DMF.cp
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- //
- // Quickdraw 3D sample code
- //
- // Netscape plugin for displaying a stream of 3DMF data
- //
- // Rick Evans, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com)
- //
- // The following functions were adapted from the NetScape sample ViewPict.
- //
- // ©1996 Apple Computer Inc., All Rights Reserved
- //
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- #ifndef _NPAPI_H_
- #include "npapi.h"
- #endif
-
- // for QuickDraw 3D
- #include <QD3D.h>
- #include <QD3DMath.h>
- #include <QD3DGroup.h>
- #include <QD3DStyle.h>
- #include <QD3DView.h>
-
- #include "View3DMF.h"
- #include "MetaFileView.h"
- #include "MyErrorHandler.h"
-
- static OSErr AppendData(PluginInstance* This, unsigned long* len, void *buffer) ;
- static Boolean StartDraw(NPWindow* window);
- static void EndDraw(NPWindow* window);
- static void DoDraw(PluginInstance* This);
-
- CGrafPort gSavePort;
- CGrafPtr gOldPort;
-
-
- //------------------------------------------------------------------------------------
- // NPP_Initialize:
- // Called the first time the plugin is loaded this Netscape Navigator session.
- //------------------------------------------------------------------------------------
- NPError
- NPP_Initialize(void)
- {
- TQ3Status myStatus;
-
- // Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
- myStatus = ::Q3Initialize();
- if ( myStatus == kQ3Failure )
- {
- return(NPERR_MODULE_LOAD_FAILED_ERROR); // ??? Is there a better error?
- }
-
- // install the error handler
- // these gets called whenever a QD3D error occurs
- ::Q3Error_Register( MyErrorHandler, 0L );
- ::Q3Warning_Register( MyWarningHandler, 0L );
-
- // create region used by netscape to save GrafPort state.
- gSavePort.clipRgn = ::NewRgn();
- return NPERR_NO_ERROR;
- }
-
-
- //------------------------------------------------------------------------------------
- // NPP_Shutdown:
- // Called when plugin is unuloaded, usually when Netscape Navigator is shutdown.
- //------------------------------------------------------------------------------------
- void
- NPP_Shutdown(void)
- {
- TQ3Status myStatus;
-
- // Close our connection to the QuickDraw 3D library
- myStatus = ::Q3Exit();
-
- if ( myStatus == kQ3Failure )
- DebugStr("\pQ3Exit returned failure.");
-
- // release region used by netscape to save GrafPort state.
- if (gSavePort.clipRgn)
- ::DisposeRgn(gSavePort.clipRgn);
- }
-
-
- //------------------------------------------------------------------------------------
- // NPP_New:
- // Called to create a new instance of plugin.
- //------------------------------------------------------------------------------------
- NPError
- NPP_New(NPMIMEType pluginType, // MIME type that this plug-in is handling
- NPP instance, // handle which uniquely describes this instance
- uint16 mode, // indicates whether this instance is embedded or not
- int16 argc,
- char* argn[],
- char* argv[],
- NPSavedData* saved)
- {
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
-
- instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
- PluginInstance* This = (PluginInstance*) instance->pdata;
- if (This != NULL)
- {
- TQ3Point3D myOrigin = { 0.0, 0.0, 0.0 } ;
-
- This->fWindow = NULL;
-
- This->fMode = mode; // Mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
-
- This->fBuffer = NULL;
- This->fBufferLength = 0;
-
- This->fView = NULL;
-
- SetRect (&This->fRect, 0, 0, 50, 50);
-
- // the main display group:
- This->fModel = NULL ;
-
- // the drawing styles:
- This->fInterpolation = ::Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
- if (This->fInterpolation == NULL)
- goto bail;
-
- This->fBackFacing = ::Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
- if (This->fBackFacing == NULL)
- goto bail1;
-
- This->fFillStyle = ::Q3FillStyle_New(kQ3FillStyleFilled ) ;
- if (This->fFillStyle == NULL)
- goto bail2;
-
- This->fGroupScale = 1;
- This->fGroupCenter = myOrigin ;
-
- // set the rotation matrix the identity matrix
- ::Q3Matrix4x4_SetIdentity(&This->fRotation);
-
- return NPERR_NO_ERROR;
- }
- else
- {
- SysBeep (1L);
- goto bail;
- }
-
- bail2:
- ::Q3Object_Dispose(This->fBackFacing);
- bail1:
- ::Q3Object_Dispose(This->fInterpolation);
- bail:
- SysBeep (1L);
- return NPERR_OUT_OF_MEMORY_ERROR;
- }
-
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_Destroy:
- // Called to delete a specific instance of a plug-in
- //------------------------------------------------------------------------------------
- NPError
- NPP_Destroy(NPP instance, NPSavedData** save)
- {
- if (instance == NULL)
- {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
-
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- if (This != NULL)
- {
- if (This->fView != NULL)
- {
- ::Q3Object_Dispose(This->fView) ; // the view for the scene
- }
-
- if (This->fModel != NULL)
- {
- ::Q3Object_Dispose(This->fModel) ; // object in the scene being modelled
- This->fModel = NULL ;
- }
-
- if (This->fInterpolation != NULL)
- {
- ::Q3Object_Dispose(This->fInterpolation) ; // interpolation style used when rendering
- }
-
- if (This->fBackFacing != NULL)
- {
- ::Q3Object_Dispose(This->fBackFacing) ; // whether to draw shapes that face away from the camera
- }
-
- if (This->fFillStyle != NULL)
- {
- ::Q3Object_Dispose(This->fFillStyle) ; // whether drawn as solid filled object or decomposed to components
- }
-
- if (This->fBuffer)
- {
- ::DisposeHandle(This->fBuffer);
- This->fBuffer = NULL;
- This->fBufferLength = 0;
- }
-
- NPN_MemFree(instance->pdata);
-
- instance->pdata = NULL;
- }
-
- return NPERR_NO_ERROR;
- }
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_SetWindow:
- // Called to provide a window for the plug-in to draw into.
- //------------------------------------------------------------------------------------
- NPError
- NPP_SetWindow(NPP instance, NPWindow* window)
- {
- NP_Port *port = (NP_Port *) window->window ;
- TQ3CameraObject holdCamera = NULL;
-
- if (instance == NULL)
- {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
-
- PluginInstance* This = (PluginInstance*) instance->pdata ;
-
- if (This->fView != NULL)
- {
- ::Q3View_GetCamera(This->fView, &holdCamera); // keep reference to camera
- ::Q3Object_Dispose(This->fView) ;
- }
-
- SetRect (&This->fRect, 0, 0, window->width, window->height ) ;
-
- This->fView = MyNewView( (GrafPtr) port->port, &This->fRect ) ;
-
- if (This->fView == nil)
- {
- return NPERR_GENERIC_ERROR; /// ??? Got a better error?
- }
-
- if (holdCamera != NULL)
- {
- ::Q3View_SetCamera(This->fView, holdCamera); // restore saved camera onject
- ::Q3Object_Dispose(holdCamera) ; // decrement reference count
- }
-
- This->fWindow = window;
-
- return NPERR_NO_ERROR;
- }
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_NewStream:
- // Called to notifies an instance of a new data stream.
- //------------------------------------------------------------------------------------
- NPError NPP_NewStream(NPP instance,
- NPMIMEType type, //MIME-type of the stream
- NPStream *stream,
- NPBool seekable, // is stream known to be capable of byte-range requests
- uint16 *stype) // stream modes other than the default (NPNormal)
- {
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- This->fBusy = TRUE; // We’re loading now
-
- return NPERR_NO_ERROR;
- }
-
-
-
-
- //
- // *Developers*:
- // These next 2 functions are directly relevant in a plug-in which handles the
- // data in a streaming manner. If you want zero bytes because no buffer space
- // is YET available, return 0. As long as the stream has not been written
- // to the plugin, Navigator will continue trying to send bytes. If the plugin
- // doesn't want them, just return some large number from NPP_WriteReady(), and
- // ignore them in NPP_Write(). For a NP_ASFILE stream, they are still called
- // but can safely be ignored using this strategy.
- //
-
- int32 STREAMBUFSIZE = 0X0FFFFFFF; // If we are reading from a file in NPAsFile
- // mode so we can take any size stream in our
- // write call (since we ignore it)
-
- //------------------------------------------------------------------------------------
- // NPP_WriteReady:
- //------------------------------------------------------------------------------------
- int32
- NPP_WriteReady(NPP instance, NPStream *stream)
- {
- if (instance != NULL)
- {
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- }
-
- return STREAMBUFSIZE; // Number of bytes ready to accept in NPP_Write()
- }
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_Write:
- //------------------------------------------------------------------------------------
- int32
- NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
- {
- if (instance != NULL)
- {
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- AppendData(This, (unsigned long*) &len, buffer);
- }
-
- return len; // The number of bytes accepted
- }
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_DestroyStream:
- // Called to close and delete the stream.
- //------------------------------------------------------------------------------------
- NPError
- NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
- {
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- This->fBusy = false; // No longer loading
-
- if (This->fBuffer != NULL) // Pictures have 512 extra bytes of data at the beginning
- {
-
- if (This->fModel != NULL)
- {
- ::Q3Object_Dispose(This->fModel);
- This->fModel = NULL;
- }
-
- ::HLock(This->fBuffer);
-
- This->fModel = MyNewModelFromBuffer( This ) ;
-
- ::HUnlock(This->fBuffer);
-
- ::DisposeHandle(This->fBuffer);
- This->fBuffer = NULL;
- This->fBufferLength = 0;
-
- AdjustCamera(This, This->fRect.right, This->fRect.bottom ) ;
-
- if (StartDraw(This->fWindow))
- {
- DoDraw(This);
- EndDraw(This->fWindow);
- }
- }
-
- return NPERR_NO_ERROR;
- }
-
-
- //------------------------------------------------------------------------------------
- // NPP_StreamAsFile:
- //------------------------------------------------------------------------------------
- void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
- {
- // We don’t support files
- }
-
-
-
- //------------------------------------------------------------------------------------
- // NPP_Print:
- //------------------------------------------------------------------------------------
- void NPP_Print(NPP instance, NPPrint* printInfo)
- {
- if (instance != NULL)
- {
- PluginInstance* This = (PluginInstance*) instance->pdata;
-
- if (printInfo->mode == NP_FULL)
- {
- //
- // If we’re fullscreen, we don’t want to take over printing,
- // so return false. NPP_Print will be called again with
- // mode == NP_EMBED.
- //
- printInfo->print.fullPrint.pluginPrinted = false;
- }
- else // If not fullscreen, we must be embedded
- {
- NPWindow* printWindow = &(printInfo->print.embedPrint.window);
- if (StartDraw(printWindow))
- {
- DoDraw(This);
- EndDraw(printWindow);
- }
- }
- }
-
- }
-
-
- //------------------------------------------------------------------------------------
- // NPP_HandleEvent:
- // Mac-only.
- //------------------------------------------------------------------------------------
- int16 NPP_HandleEvent(NPP instance, void* event)
- {
- Boolean eventHandled = false;
- if (instance == NULL)
- return eventHandled;
-
- PluginInstance* This = (PluginInstance*) instance->pdata;
- if (This != NULL && event != NULL)
- {
- EventRecord* ev = (EventRecord*) event;
- switch (ev->what)
- {
- //
- // Draw ourselves on update events
- //
- case updateEvt:
- DoDraw(This);
- eventHandled = true;
- break;
-
- case nullEvent:
- // we received a null event, rotate the model
- TQ3Matrix4x4 tmp;
-
-
- if (StartDraw(This->fWindow))
- {
- DoDraw(This);
- EndDraw(This->fWindow);
- }
- Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
- Q3Matrix4x4_Multiply(&This->fRotation, &tmp, &This->fRotation);
- break;
-
- default:
- break;
- }
- }
-
- return eventHandled;
- }
-
-
-
- //------------------------------------------------------------------------------------
- // AppendData:
- //------------------------------------------------------------------------------------
- OSErr AppendData(PluginInstance* This, unsigned long* len, void *buffer)
- {
- OSErr resultCode = noErr;
-
- if (This->fBuffer == NULL) // Have not yet allocated buffer
- {
- Size appMem = 0;
- Size tmpMem = 0;
-
- This->fBufferLength = 0;
-
- appMem = ::MaxMem(&appMem);
- tmpMem = ::TempMaxMem(&tmpMem);
-
-
- // Allocate memory in the heap with the most room.
- if (tmpMem >= appMem)
- {
- This->fBuffer = ::TempNewHandle( *len, &resultCode) ;
- }
- else
- {
- This->fBuffer = ::NewHandle(*len) ;
- }
-
- if ((This->fBuffer == NULL) || (resultCode != noErr))
- {
- if (resultCode != noErr)
- {
- resultCode = MemError();
- }
-
- /// DebugStr("\p Out of Memory") ;
-
- *len = 0;
- return resultCode;
- }
- }
- else
- {
- ::SetHandleSize(This->fBuffer, GetHandleSize(This->fBuffer)+*len);
- }
-
- ::BlockMove(buffer, (*This->fBuffer)+This->fBufferLength, *len);
-
- This->fBufferLength += *len;
-
- return noErr;
- }
-
-
- //------------------------------------------------------------------------------------
- // StartDraw:
- //------------------------------------------------------------------------------------
- Boolean StartDraw(NPWindow* window)
- {
- if (window == NULL)
- return FALSE;
- NP_Port* port = (NP_Port*) window->window;
- if (window->clipRect.left < window->clipRect.right)
- {
- // Preserve the old port
- ::GetPort((GrafPtr*)&gOldPort);
- ::SetPort((GrafPtr)port->port);
- // Preserve the old drawing environment
- gSavePort.portRect = port->port->portRect;
- gSavePort.txFont = port->port->txFont;
- gSavePort.txFace = port->port->txFace;
- gSavePort.txMode = port->port->txMode;
- gSavePort.rgbFgColor = port->port->rgbFgColor;
- gSavePort.rgbBkColor = port->port->rgbBkColor;
- ::GetClip(gSavePort.clipRgn);
- // Setup our drawing environment
- Rect clipRect;
- clipRect.top = window->clipRect.top + port->porty;
- clipRect.left = window->clipRect.left + port->portx;
- clipRect.bottom = window->clipRect.bottom + port->porty;
- clipRect.right = window->clipRect.right + port->portx;
- ::SetOrigin(port->portx,port->porty);
- ::ClipRect(&clipRect);
- clipRect.top = clipRect.left = 0;
- TextSize(window->height);
- TextFont(geneva);
- TextMode(srcCopy);
- RGBColor col;
- col.red = col.green = col.blue = 30000;
- RGBForeColor(&col);
- col.red = col.green = col.blue = 65000;
- RGBBackColor(&col);
- return TRUE;
- }
- else
- return FALSE;
- }
-
-
- //------------------------------------------------------------------------------------
- // EndDraw:
- //------------------------------------------------------------------------------------
- void EndDraw(NPWindow* window)
- {
- NP_Port* port = (NP_Port*) window->window;
- ::SetOrigin(gSavePort.portRect.left, gSavePort.portRect.top);
- ::SetClip(gSavePort.clipRgn);
- CGrafPtr myPort;
- ::GetPort((GrafPtr*)&myPort);
- myPort->txFont = gSavePort.txFont;
- myPort->txFace = gSavePort.txFace;
- myPort->txMode = gSavePort.txMode;
- ::RGBForeColor(&gSavePort.rgbFgColor);
- ::RGBBackColor(&gSavePort.rgbBkColor);
- ::SetPort((GrafPtr)gOldPort);
- }
-
-
- //------------------------------------------------------------------------------------
- // DoDraw:
- //------------------------------------------------------------------------------------
- void DoDraw(PluginInstance* This)
- {
- if (This->fBusy ) // Do not draw if we are not done
- return;
-
- DocumentDraw3DData( This ) ;
- }
-
-